<template>
  <div class="container">
    <div class="about">
      <el-container>
        <el-header>
          云课招新考试
          <div style="position: absolute; right: 20px; top: 0px">
            考试剩余时间：<span style="color: orange">{{ endTimeStr }}</span>
          </div>
        </el-header>
        <el-container>
          <el-aside width="200px"
            ><div>
              <el-tag
                class="tag"
                v-for="(o, index) in topics"
                :key="o.sid"
                :type="nowIndex == index ? '' : o.type ? o.type : 'info'"
                @click="changeNowTopic(index)"
                >第{{ index + 1 }}题</el-tag
              >
            </div></el-aside
          >

          <el-container>
            <el-main>
              <el-card shadow="always">
                <div slot="header" class="clearfix">
                  <span>题目</span>
                </div>
                <p
                  style="text-indent: 2em; white-space: pre-wrap"
                  v-html="nowTopic.topic"
                ></p>
              </el-card>
              <div v-loading="loading">
                <el-card
                  shadow="always"
                  style="margin-top: 30px"
                  v-if="codePreviewFlag"
                >
                  <pre-code
                    :codes="codes != '' ? '\n' + codes : '//暂无代码'"
                    :modeValue="modeValue"
                  ></pre-code>

                  <!-- <pre :class="['language-' + modeValue, 'line-numbers']">
      <code :class="['language-' + modeValue, 'line-numbers']"  >
        {{ codes }}
      </code>
    </pre> -->
                </el-card>
              </div>
            </el-main>
            <el-footer>
              <div class="comit_btn">
                <el-button
                  type="info"
                  style="position: absolute; left: 30%; top: 10px"
                  @click="seeCode"
                  >代码预览</el-button
                >
                <el-button
                  type="primary"
                  style="position: absolute; right: 30%; top: 10px"
                  @click="handleAdd"
                  >代码提交</el-button
                >

                <el-button
                  type="primary"
                  style="position: absolute; right: 10%; top: 10px"
                  @click="changeNowIndex"
                  v-if="nowIndex < topics.length - 1"
                  >下一题</el-button
                >

                <el-button
                  type="primary"
                  style="position: absolute; right: 10%; top: 10px"
                  @click="generalPreview"
                  v-if="nowIndex >= topics.length - 1"
                  >总代码预览</el-button
                >
              </div>
            </el-footer>
          </el-container>
        </el-container>
      </el-container>
    </div>

    <el-dialog :title="title" :visible.sync="open" width="70%">
      <el-form ref="form" :model="form" label-width="80px">
        <el-select class="code-mode-select" v-model="mode" @change="changeMode">
          <el-option
            v-for="mode in modes"
            :key="mode.value"
            :label="mode.label"
            :value="mode.value"
          >
          </el-option>
        </el-select>
        <el-form-item label="代码：">
          <div class="in-coder-panel">
            <textarea ref="textarea" style="text-align: lefr"></textarea>
          </div>
        </el-form-item>
      </el-form>
      <el-button @click="comitCode">提交</el-button>
    </el-dialog>
  </div>
</template>

<script>
import Prism from "prismjs"; // 引入插件
import "prismjs/themes/prism.css"; // 引入样式

// 引入全局实例
import CodeMirror from "codemirror";
// 核心样式
import "codemirror/lib/codemirror.css";
// 引入主题后还需要在 options 中指定主题才会生效
import "codemirror/theme/idea.css";
import "codemirror/theme/eclipse.css";
import "codemirror/theme/darcula.css";
import "codemirror/theme/blackboard.css";
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库
// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ，所以此处才把对应的 JS 提前引入
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/clike/clike.js";

// import "codemirror/mode/css/css.js";
// import "codemirror/mode/xml/xml.js";
// import "codemirror/mode/shell/shell.js";
// import "codemirror/mode/sql/sql.js";
// import "codemirror/mode//vue/vue.js";
// import "codemirror/mode/";
//代码补全提示
import "codemirror/addon/hint/anyword-hint.js";
import "codemirror/addon/hint/css-hint.js";
import "codemirror/addon/hint/html-hint.js";
import "codemirror/addon/hint/javascript-hint.js";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/sql-hint.js";
import "codemirror/addon/hint/xml-hint.js";
//代码版本差异比较
import "codemirror/addon/merge/merge.js";
import "codemirror/addon/merge/merge.css";
import DiffMatchPatch from "diff-match-patch";
import PreCode from "../components/PreCode.vue";
window.diff_match_patch = DiffMatchPatch;
window.DIFF_DELETE = -1;
window.DIFF_INSERT = 1;
window.DIFF_EQUAL = 0;
export default {
  components: { PreCode },
  mounted() {
    Prism.highlightAll();
  },
  data() {
    return {
      endTime: 0,
      endTimeStr: "",
      loading: true,
      topics: [],
      nowIndex: 0,
      nowTopic: {},
      codePreviewFlag: false,
      // 内部真实的内容
      code: "//代码替换",
      // 代码预览
      codes: ``,
      // 默认的语法类型
      mode: "java",
      modeValue: "java",
      // 编辑器实例
      coder: null,
      // 默认配置
      options: {
        // 缩进格式
        tabSize: 4,
        // 主题，对应主题库 JS 需要提前引入
        theme: "eclipse",
        // 显示行号
        lineNumbers: true,
        line: true,
        extraKeys: { Ctrl: "autocomplete" },
      },
      // 支持切换的语法高亮类型，对应 JS 已经提前引入
      // 使用的是 MIME-TYPE ，不过作为前缀的 text/ 在后面指定时写死了
      form: {},
      modes: [
        // {
        //   value: "css",
        //   label: "CSS",
        // },
        {
          value: "javascript",
          label: "Javascript",
          values: "javascript",
        },
        {
          value: "x-c++src",
          label: "C++",
          values: "cpp",
        },
        {
          value: "x-java",
          label: "Java",
          values: "java",
        },
        {
          value: "x-c",
          label: "C语言",
          values: "c",
        },
      ],
      // 弹出层标题
      title: "",
      titleBBB: "",
      // 是否显示弹出层
      open: false,
      openBBB: false,
    };
  },

  created() {
    this.loading = false;
    this.mode = localStorage.getItem("mode");
    console.log(this.mode);
    this.$http.get("/getQuestion").then((res) => {
      console.log(res);
      this.topics = res.data.data.question;
      const reg = /\/api\//g;
      this.topics.filter((item) => {
        item.topic = item.topic.replace(reg, this.$httpUrl);
      });

      console.log(this.nowTopic, "asd");
      this.endTime = res.data.data.endTime;
      // console.log(this.topics);
      // console.log(this.endTime);
      this.nowIndex = 0;
      // this.nowIndex = index;
      this.nowTopic = this.topics[0];
      console.log(this.nowTopic);
      this.getTestPaper(this.nowTopic.tid);
      // var date = new Date(this.endTime - new Date().getTime()); // 参数需要毫秒数，所以这里将秒数乘于 1000
      // const Y = date.getFullYear() + "-";
      // const M =
      //   (date.getMonth() + 1 < 10
      //     ? "0" + (date.getMonth() + 1)
      //     : date.getMonth() + 1) + "-";
      // const D = date.getDate() + " ";
      // const h = date.getHours() + ":";
      // const m = date.getMinutes() + ":";
      // const s = date.getSeconds();
      // // console.log();
      // this.endTimeStr = Y + M + D + h + m + s;
      setInterval(() => {
        this.endTimeStr = this.intervalTime(new Date().getTime(), this.endTime);
      }, 1000);
    });

    // for (let i = 1; i < 10; i++) {
    //   this.topics.push({ id: i + 1, context: "123123123123" });
    // }
  },

  methods: {
    // 时间差
    intervalTime(startTime, endTime) {
      let i = endTime - startTime;
      let modh = i % (1000 * 60 * 60 * 24); // 天数外剩余的
      let day = (i - modh) / 1000 / 60 / 60 / 24; // 剩余天数
      let modm = modh % (1000 * 60 * 60); // 小时外剩余的
      let h = (modh - modm) / 1000 / 60 / 60; // 剩余小时
      let mods = modm % (1000 * 60); // 分钟外剩余的
      let m = (modm - mods) / 1000 / 60; // 剩余分
      let s = Math.floor(mods / 1000); // 剩余秒
      return `${day}天${h}小时${m}分钟${s}秒`;
    },
    generalPreview() {
      console.log("总预览");
      this.$router.push("/perview");
    },
    changeNowIndex() {
      // 代码提交
      if (!this.nowTopic.flag) {
        this.$message.info("代码未提交");
        this.$set(this.topics[this.nowIndex], "type", "info");
      }
      // 初始化参数值
      this.code = "//代码替换";
      this.codes = ``;
      // 状态改变
      // this.$set(this.topics[this.nowIndex], "type", "success");

      // 题目切换
      this.nowIndex++;
      this.nowTopic = this.topics[this.nowIndex];

      if (this.codePreviewFlag) {
        this.codePreviewFlag = !this.codePreviewFlag;
      }
      this.selectCode(this.nowIndex);
      // this.codePreviewFlag = false;

      // setTimeout(() => {
      //   this.codePreviewFlag = !this.codePreviewFlag;
      // }, 400);
    },
    // 查询单题目答案
    getTestPaper(tid) {
      this.loading = true;
      this.$http.get(`/getTestPaper/${tid}`).then((res) => {
        console.log("getTestPaper", res);

        if (res.data.data) {
          this.nowTopic.flag = true;
          this.topics[this.nowIndex].type = "success";
          const codeobj = JSON.parse(res.data.data.answer);
          this.modeValue = this.mode = codeobj.type;
          this.code = this.codes = codeobj.code;
          // console.log(codeobj.code,"=====");

          this.loading = false;
        } else {
          this.$message.info("尚未提交代码");
          this.code = this.codes = "//代码替换";
          this.loading = false;
        }
        setTimeout(() => {
          this.codePreviewFlag = true;
          this.loading = false;
        }, 100);
      });
    },
    seeCode() {
      if (!this.codePreviewFlag) {
        // this.loading = true;
        this.selectCode(this.nowIndex);
      }
      this.codePreviewFlag = !this.codePreviewFlag;
    },
    // 代码读取
    selectCode(index) {
      this.loading = true;
      console.log(index);
      const code = localStorage.getItem(index);
      if (code) {
        this.code = code;
        this.codes = this.code;
        this.loading = false;
        this.topics[this.nowIndex].flag = true;
        this.topics[this.nowIndex].type = "success";
        setTimeout(() => {
          this.codePreviewFlag = true;
        }, 100);
      } else {
        // 网络查询
        this.getTestPaper(this.topics[index].tid);
      }
    },
    changeNowTopic(index) {
      this.code = this.codes = ``;
      this.nowIndex = index;
      this.nowTopic = this.topics[index];
      if (this.codePreviewFlag) {
        this.codePreviewFlag = false;
      }
      this.selectCode(index);

      // this.nowTopic = JSON.parse(JSON.stringify(this.topics[0]));
      // this.$set(this.topics[0], "type", "success");
      // this.nowTopic[type] = "success";

      console.log(this.nowTopic);
    },
    // 初始化
    _initialize() {
      // 初始化编辑器实例，传入需要被实例化的文本域对象和默认配置
      if (!this.coder)
        this.coder = CodeMirror.fromTextArea(this.$refs.textarea, this.options);
      // 编辑器赋值
      this.coder.setValue(this.value || this.code);
      // 支持双向绑定
      this.coder.on("change", (coder) => {
        this.code = coder.getValue();
        if (this.$emit) {
          this.$emit("input", this.code);
        }
      });
      // 尝试从父容器获取语法类型
      if (this.language) {
        // 获取具体的语法类型对象
        let modeObj = this._getLanguage(this.language);
        // 判断父容器传入的语法是否被支持
        if (modeObj) {
          this.mode = modeObj.label;
        }
      }
    },
    // 获取当前语法类型
    _getLanguage(language) {
      // 在支持的语法类型列表中寻找传入的语法类型
      return this.modes.find((mode) => {
        // 所有的值都忽略大小写，方便比较
        let currentLanguage = language.toLowerCase();
        let currentLabel = mode.label.toLowerCase();
        let currentValue = mode.value.toLowerCase();
        // 由于真实值可能不规范，例如 java 的真实值是 x-java ，所以讲 value 和 label 同时和传入语法进行比较
        return (
          currentLabel === currentLanguage || currentValue === currentLanguage
        );
      });
    },
    // 更改模式
    changeMode(val) {
      // 修改编辑器的语法配置
      this.coder.setOption("mode", `text/${val}`);
      console.log(val);
      this.modeValue = this.modes.find((item) => {
        return val === item.value;
      }).values;
      console.log(this.modeValue);

      // 获取修改后的语法
      let label = this._getLanguage(val).label.toLowerCase();
      // 允许父容器通过以下函数监听当前的语法值
      this.$emit("language-change", label);
    },
    initUI(value, orig) {
      if (value == null) return;
      let target = document.getElementById("view");
      target.innerHTML = "";
      CodeMirror.MergeView(target, {
        value: value, //上次内容
        origLeft: null,
        orig: orig, //本次内容
        lineNumbers: true, //显示行号
        mode: "shell",
        highlightDifferences: true,
        styleActiveLine: true,
        matchBrackets: true,
        connect: "align",
        readOnly: true, //只读 不可修改
      });
    },
    /** 按钮操作 */
    handleAdd() {
      this.open = true;
      this.title = "代码提交";
      this.$nextTick(function () {
        this._initialize();
        console.log(this.$refs.textarea);
      });
    },
    comitCode() {
      console.log(this.code);
      this.codes = this.code;
      localStorage.setItem(this.nowIndex, this.code);
      localStorage.setItem("modeValue" + this.nowIndex, this.modeValue);
      // 拼接数据进行提交
      const codeobj = {
        type: this.modeValue,
        code: this.code,
      };
      const codestr = JSON.stringify(codeobj);
      this.$http
        .post("/submitTitle", { tid: this.nowTopic.tid, answer: codestr })
        .then((res) => {
          console.log(res);
          if (res.data.message == "ok") {
            this.nowTopic.flag = true;
            this.topics[this.nowIndex].type = "success";
            this.open = false;
            this.loading = false;
            if (this.codePreviewFlag) {
              this.codePreviewFlag = !this.codePreviewFlag;
            }
            setTimeout(() => {
              this.codePreviewFlag = !this.codePreviewFlag;
            }, 200);
            this.$message({
              message: "答案提交成功",
              type: "success",
            });
          }
        });
      // this.code = "";
    },
  },
};
</script>
<style lang="less" scoped>
.container {
  background-image: linear-gradient(to bottom right, #46fca7, #3fd5fb);
  height: 100vh;
}
.about {
  width: 70%;

  background: #fff;
  border-radius: 20px;
  min-width: 1000px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.tag {
  width: 90%;
  display: block;
  margin: 10px auto;
}
.el-header,
.el-footer {
  font-size: 20px;
  background-color: #f4f7f9;

  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  /* background-color: #fff; */
  color: #333;
  text-align: center;
  line-height: 200px;
  border-right: 1px rgba(0, 0, 0, 0.3) solid;
}

.el-main {
  /* background-color: #fff; */
  color: #333;
  text-align: left;
  height: 80vh;
  font-size: 18px;
  word-wrap: normal;
  word-break: normal;
}

body > .el-container {
  margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
  line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
  line-height: 320px;
}

.comit_btn {
  position: relative;
}
</style>